package com.wonder.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Random;

import org.apache.commons.lang3.StringUtils;

import com.google.common.base.Joiner;

import jnr.ffi.Struct.int16_t;


public class RedGameUtils {

	    //连接符
	    public static final String SPLIT = "|";
	    //连接符，正则中使用
	    public static final String SPLIT_REGEX = "\\|";
	    //空连接符
	    public static final String EMPTY_SPLIT = " ";

	    /**
	     * 向下取整保留两位小数
	     *
	     * @param bigDecimal
	     * @return
	     */
	    public static String trimBigDecimal(BigDecimal bigDecimal) {
	        if (Objects.isNull(bigDecimal)) {
	            return StringUtils.EMPTY;
	        }
	        return bigDecimal.setScale(0, BigDecimal.ROUND_DOWN).toString();
	    }

	    /**
	     * 根据指定金额生成指定个数红包，
	     *
	     * @param money 金额
	     * @param num   红包数
	     * @return
	     */
	    public static String generatePackageMoney(BigDecimal money, int num) {
	        return Joiner.on(SPLIT).join(generatePackageMoneyList(money, num));
	    }
	    
	    /**
	     * 根据红包列表获取字符串，
	     *
	     * @param packetList 金额列表
	     * @return
	     */
	    public static String generatePackageMoney(List<String> packetList) {
	        return Joiner.on(SPLIT).join(packetList);
	    }

	/**
	 * 根据参数，获取有雷的表
	 * @param money
	 * @param num
	 * @param parameter
	 * @param bomb
	 * @return
	 */
		public static List<String> generateControlledMoneyList(BigDecimal money,int num, int parameter,String bomb){

			if(parameter==0) return generatePackageMoneyList(money,num); //Normal

			List<String> packageMoneyList = generatePackageMoneyList(money,num);
			while (packageBombNumber(packageMoneyList,bomb) > parameter -1){
				packageMoneyList=generatePackageMoneyList(money,num);
			}
			return packageMoneyList;

		}

	/**
	 *
	 * @param money
	 * @param num Package numbers
	 * @param retry_times Retry times if no bomb
	 * @param bomb
	 * @return
	 */
		public static List<String> generateRetriedMoneyList(BigDecimal money,int num, int retry_times,String bomb){

			if(retry_times==0) return generatePackageMoneyList(money,num); //Normal

			List<String> packageMoneyList = generatePackageMoneyList(money,num);
			while (retry_times >0 && packageBombNumber(packageMoneyList,bomb)==0){
				packageMoneyList=generatePackageMoneyList(money,num);
				retry_times--;
			}
			return packageMoneyList;

		}

	    public static List<String> generatePackageMoneyList(BigDecimal money, int num) {
	        List<String> packageMoneyList = new ArrayList<>();
	        Random random = new Random();
	        BigDecimal min = new BigDecimal("0");

	        money = money.setScale(0, BigDecimal.ROUND_DOWN);

	        BigDecimal middle = money.divide(BigDecimal.valueOf(num), RoundingMode.HALF_UP);

	        BigDecimal redMoney;
	        for (int i = num; i > 0; i--) {
	            if (i == 1) {
	                packageMoneyList.add(trimBigDecimal(money));
	            } else {
	                do {
	                    redMoney = money.multiply(BigDecimal.valueOf(random.nextDouble()));
	                    redMoney = new BigDecimal(trimBigDecimal(redMoney));
	                } while (redMoney.compareTo(min) < 0 || redMoney.compareTo(middle) > 0);

	                money = money.subtract(redMoney);
	                packageMoneyList.add(trimBigDecimal(redMoney));
	                middle = money.divide(BigDecimal.valueOf((i - 1)), RoundingMode.HALF_UP);
	            }
	        }
	        Collections.shuffle(packageMoneyList);
	        return packageMoneyList;
	    }


	    /**
	     * 红包尾数是否包含中雷数字
	     *
	     * @param pickRedPackage 红包
	     * @param bomb           雷，多雷以"|"连接
	     * @return
	     */
	    public static boolean containsBombNumber(String pickRedPackage, String bomb) {
	        if (StringUtils.isBlank(pickRedPackage) || StringUtils.isBlank(bomb)) {
	            return false;
	        }

	        return bomb.contains(pickRedPackage.substring(pickRedPackage.length() - 1));
	    }

	    /**
	     * 多雷是否中雷
	     *
	     * @param packageMoney
	     * @param bomb
	     * @return
	     */
	    public static boolean containsMultipleBombNumber(String packageMoney, String bomb) {
	        if (StringUtils.isBlank(packageMoney) || StringUtils.isBlank(bomb)) {
	            return false;
	        }

	        List<String> lastNumbers = getLastRedPackageCode(packageMoney);
	        return lastNumbers.containsAll(Arrays.asList(bomb.split(SPLIT_REGEX)));
	    }

	    /**
	     * 红包包含雷的个数
	     *
	     * @param packageMoney
	     * @param bomb
	     * @return
	     */
	    public static int packageBombNumber(String packageMoney, String bomb) {
	        int num = 0;
	        if (StringUtils.isBlank(packageMoney) || StringUtils.isBlank(bomb)) {
	            return num;
	        }
	        for (String redPackage : packageMoney.split(SPLIT_REGEX)) {
	            if (containsBombNumber(redPackage, bomb)) {
	                num++;
	            }
	        }
	        return num;
	    }

	/**
	 * 红包包含雷的个数
	 *
	 * @param packageMoney
	 * @param bomb
	 * @return
	 */
	public static int packageBombNumber(List<String> packageMoney, String bomb) {
		int num = 0;
		if (packageMoney.size()==0 || StringUtils.isBlank(bomb)) {
			return num;
		}
		for (String redPackage : packageMoney) {
			if (containsBombNumber(redPackage, bomb)) {
				num++;
			}
		}
		return num;
	}
	    
	    /**
	     * 红包包含雷的个数,去除免死
	     *
	     * @param packageMoney
	     * @param bomb
	     * @return
	     */
	    public static int packageBombNumberWithExempt(String packageMoney, String bomb) {
	        int num = 0;
	        if (StringUtils.isBlank(packageMoney) || StringUtils.isBlank(bomb)) {
	            return num;
	        }
	        String[] list=packageMoney.split(SPLIT_REGEX);
	        
	        for(int i=1;i<list.length;i++) {
	        	 if (containsBombNumber(list[i], bomb)) {
		                num++;
		            }
	        }
	        return num;
	    }

	    /**
	     * 把用"|"连接的红包转换为数值相加返回
	     *
	     * @param packageMoney
	     * @return
	     */
	    public static BigDecimal convertPackageToMoney(String packageMoney) {
	        BigDecimal money = BigDecimal.ZERO;
	        if (StringUtils.isBlank(packageMoney)) {
	            return money;
	        }

	        for (String redPackage : packageMoney.split(SPLIT_REGEX)) {
	            money = money.add(new BigDecimal(redPackage));
	        }
	        return money;
	    }

	    /**
	     * 获取红包尾数集合
	     *
	     * @param packageMoney 红包
	     * @return
	     */
	    public static List<String> getLastRedPackageCode(String packageMoney) {
	        if (StringUtils.isBlank(packageMoney)) {
	            return Collections.emptyList();
	        }

	        List<String> lastNumbers = new ArrayList<>();
	        for (String redPackage : packageMoney.split(SPLIT_REGEX)) {
	            lastNumbers.add(redPackage.substring(redPackage.length() - 1));
	        }
	        return lastNumbers;
	    }

	/**
	 * 获取红包尾数集合
	 *
	 * @param packageMoney 红包
	 * @return
	 */
	public static List<String> getLastRedPackageCode(List<String> packageMoney) {

		List<String> lastNumbers = new ArrayList<>();
		for (String redPackage : packageMoney) {
			lastNumbers.add(redPackage.substring(redPackage.length() - 1));
		}
		return lastNumbers;
	}

	    /**
	     * 连接集合为字符串
	     *
	     * @param collection
	     * @return
	     */
	    public static String concatBySplit(Collection<String> collection) {
	        if (Objects.isNull(collection) || collection.isEmpty()) {
	            return StringUtils.EMPTY;
	        }

	        StringBuilder result = new StringBuilder();
	        for (String s : collection) {
	            result.append(s).append(SPLIT);
	        }
	        result.deleteCharAt(result.length() - 1);
	        return result.toString();
	    }

	    /**
	     * 连接集合为字符串
	     *
	     * @param collection
	     * @return
	     */
	    public static String concatByEmptySplit(Collection<String> collection) {
	        if (Objects.isNull(collection) || collection.isEmpty()) {
	            return StringUtils.EMPTY;
	        }

	        StringBuilder result = new StringBuilder();
	        for (String s : collection) {
	            result.append(s).append(EMPTY_SPLIT);
	        }
	        result.deleteCharAt(result.length() - 1);
	        return result.toString();
	    }


	    /**
	     * 判断一个容器是否包含另一个容器所有元素
	     *
	     * @param bigCollection
	     * @param smallCollection
	     * @param <T>
	     * @return
	     */
	    public static <T> boolean containsAll(Collection<T> bigCollection, Collection<T> smallCollection) {
	        List<T> bigList = new ArrayList<>(bigCollection);
	        List<T> smallList = new ArrayList<>(smallCollection);

	        for (T next : smallList) {
	            if (bigList.contains(next)) {
	                bigList.remove(next);
	            } else {
	                return false;
	            }
	        }
	        return true;
	    }

	    public static <T> void removeAll(Collection<T> bigCollection, Collection<T> smallCollection) {
	        if (Objects.isNull(smallCollection) || smallCollection.isEmpty()) {
	            return;
	        }
	        for (T next : smallCollection) {
	            if (bigCollection.contains(next)) {
	                bigCollection.remove(next);
	            }
	        }
	    }

//	    public static void main(String[] args) {
////	        System.out.println(generatePackageMoney(new BigDecimal(20), 10));
////	        System.out.println(containsMultipleBombNumber("1.02|2.05|.06|", "5|6"));
//
//	        for (int i = 0; i < 1000; i++) {
//	            String packageMoney = generatePackageMoney(new BigDecimal("1.55"), 5);
//	            System.out.println(i);
//	            System.out.println(packageMoney);
//	            System.out.println(convertPackageToMoney(packageMoney));
//	        }
//	    }
   

}
